package cn.yyh.serviceOrg.service.impl;

import cn.yyh.commons.constant.Constants;
import cn.yyh.commons.domain.LoginInfo;
import cn.yyh.commons.exception.MyException;
import cn.yyh.commons.utils.HttpClientUtils;
import cn.yyh.commons.utils.MD5Util;
import cn.yyh.commons.utils.R;
import cn.yyh.serviceOrg.entity.User;
import cn.yyh.serviceOrg.entity.WxUser;
import cn.yyh.serviceOrg.entity.dto.LoginDTO;
import cn.yyh.serviceOrg.mapper.LoginInfoMapper;
import cn.yyh.serviceOrg.mapper.UserMapper;
import cn.yyh.serviceOrg.mapper.WxUserMapper;
import cn.yyh.serviceOrg.service.ILoginService;
import cn.yyh.serviceOrg.utils.JudgeUtil;
import cn.yyh.serviceOrg.utils.TokenUtil;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;

/**
 * @author 杨永航
 * @version 1.0
 * @Title: LoginServiceImpl
 * @Package: cn.yyh.user.service.impl
 * @date 2021/7/2
 */
@Service
public class LoginServiceImpl implements ILoginService {
    @Autowired
    private LoginInfoMapper loginInfoMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserServiceImpl userService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WxUserMapper wxUserMapper;

    /**
     * 账号登陆
     * @version: 1.0
     * @param loginDTO 数据
     * @return: Map<String,Object>
     * @author: 杨永航
     * @date: 2021/7/4
     */
    @Override
    public Map<String, Object> accountLogin(LoginDTO loginDTO) {
        // 1.判断参数是否为空
//        if (ObjectUtils.isEmpty(loginDTO.getUsername())
//                || ObjectUtils.isEmpty(loginDTO.getPassword())
//                || ObjectUtils.isEmpty(loginDTO.getType())) {
//            throw new MyException("账号密码错误,请重新输入!");
//        }
        JudgeUtil.isNull(loginDTO.getUsername(),loginDTO.getPassword(),loginDTO.getType());
        // 2.拿username和type去数据库找有没有重复
        LoginInfo loginInfo = loginInfoMapper.getByLoginDTO(loginDTO);
        if (loginInfo == null) {
            throw new MyException("账号密码错误,请重新输入!");
        }
        // 3.拿到前端传回来的密码并用查询到的盐值加密,和数据库的密码做对比
        String salt = loginInfo.getSalt();
        String password = MD5Util.encrypByMd5(salt + loginDTO.getPassword());
        if (!loginInfo.getPassword().equals(password)) {
            throw new MyException("账号密码错误,请重新输入!");
        }

        return TokenUtil.token2Redis(redisTemplate,loginInfo,30);
    }

    /**
     * 拿到前端发送的code授权码,进行数据库查询,如果有就免密登陆,如果没有就跳转到绑定页面
     * @version: 1.0
     * @param map 装code授权码
     * @return: R
     * @author: 杨永航
     * @date: 2021/7/4
     */
    @Override
    public R weChatLogin(Map<String, Object> map) {
        // 1.取出授权码,并进行校验
        String code = map.get("code").toString();
        if (!StringUtils.hasText(code) && !StringUtils.hasLength(code)) {
            throw new MyException("没有授权");
        }
        // 2.拼接发送请求的url地址,并调用httpClient工具类给微信发送请求
        String forWeChatToken = Constants.WECHAT_FOR_TOKEN.replace("APPID", Constants.WECHAT_APPID)
                .replace("SECRET", Constants.WECHAT_SECRET)
                .replace("CODE", code);
        String weChatInfo = HttpClientUtils.httpGet(forWeChatToken);
        // 3.用阿里提供json转换工具把收到的json字符串转换成对象,并拿到其中的数据
        JSONObject jsonObject = JSONObject.parseObject(weChatInfo);
        String accessToken = jsonObject.getString("access_token");
        String openId = jsonObject.getString("openid");
        // 4.用openId查数据库
        WxUser wxUser = wxUserMapper.getByOpenId(openId);
        System.out.println(wxUser);
        // 5.如果对象不为null,且userId也不为null,说明登陆过,且已绑定,直接免密登录
        if (wxUser != null && wxUser.getUser_id() != null) {
            LoginInfo loginInfo = loginInfoMapper.getByUserId(wxUser.getUser_id());

            Map<String, Object> m = TokenUtil.token2Redis(redisTemplate, loginInfo, 30);
            return R.oK().setResultObj(m);

        }
        // 6.如果都没满足要么没登录过,要么没绑定.拼接一个字符串,把数据给到前端,让前端跳转绑定页面
        String binderUrlParams = "?accessToken="+accessToken+"&openId="+openId;
        return R.error().setResultObj(binderUrlParams);
    }

    /**
     * 绑定用户,并创建wxUser数据
     * @version: 1.0
     * @param map 数据
     * @return: Map<String,Object>
     * @author: 杨永航
     * @date: 2021/7/4
     */
    @Override
    public Map<String, Object> weChatBinder(Map<String, Object> map) {
        String phone = map.get("phone").toString();
        String password = map.get("password").toString();
        String confirmPassword = map.get("confirmPassword").toString();
        String verifyCode = map.get("verifyCode").toString();
        String token = map.get("token").toString();
        String openId = map.get("openId").toString();

        if (!StringUtils.hasLength(phone)
                || !StringUtils.hasLength(password)
                || !StringUtils.hasLength(confirmPassword)
                || !StringUtils.hasLength(verifyCode)
                || !StringUtils.hasLength(token)
                || !StringUtils.hasLength(openId)) {
            throw new MyException("账号密码错误!");
        }

        if (!password.equals(confirmPassword)) {
            throw new MyException("两次密码不一致!");
        }
        String key = Constants.BUSINESS_BINDER_PREFIX+phone;
        Object temp = redisTemplate.opsForValue().get(key);
        if (temp == null) {
            throw new MyException("验证码已过期,请重新获取");
        }
        String code = temp.toString().split(":")[1];
        if (!verifyCode.equalsIgnoreCase(code)) {
            throw new MyException("验证码错误");
        }

        User byPhone = userMapper.getByPhone(phone);
        User user;
        LoginInfo loginInfo;

        if (byPhone != null) {
            String salt = byPhone.getSalt();
            String byPhonePassword = byPhone.getPassword();
            String md5 = MD5Util.encrypByMd5(salt + password);
            if (!md5.equals(byPhonePassword)) {
                throw new MyException("账号密码错误!");
            }
            user = byPhone;
            loginInfo = loginInfoMapper.getById(byPhone.getLoginInfoId());
        }else {
            user = new User();
            user.setPhone(phone);
            user.setPassword(password);
            user.setUsername(phone);
            userService.save(user);
            loginInfo = loginInfoMapper.getById(user.getLoginInfoId());
        }
        String url = Constants.WECHAT_FOR_USERINFO.replace("ACCESS_TOKEN", token)
                .replace("OPENID", openId);
        String httpGet = HttpClientUtils.httpGet(url);
        initWxUser(httpGet,user);

        return TokenUtil.token2Redis(redisTemplate,loginInfo,30);
    }

    /**
     * 判断是否存在这个wxUser,如果没有设置值并添加.如果有,绑定userId并修改
     * @version: 1.0
     * @param httpGet 从微信拿到的数据
     * @param user 当前user账号
     * @return: void
     * @author: 杨永航
     * @date: 2021/7/4
     */
    private void initWxUser(String httpGet, User user) {

        JSONObject jsonObject = JSONObject.parseObject(httpGet);
        String openid = jsonObject.getString("openid");
        WxUser wxUser = wxUserMapper.getByOpenId(openid);
        if (wxUser == null) {
            wxUser = new WxUser();
            wxUser.setOpenId(openid);
            wxUser.setNickname(jsonObject.getString("nickname"));
            wxUser.setSex(jsonObject.getInteger("sex"));
            wxUser.setAddress(jsonObject.getString("city"));
            wxUser.setHeadImgUrl(jsonObject.getString("headimgurl"));
            wxUser.setUnionId(jsonObject.getString("unionid"));
            wxUser.setUser_id(user.getId());
            wxUserMapper.save(wxUser);
        } else {
            wxUser.setUser_id(user.getId());
            wxUserMapper.update(wxUser);
        }
    }


}
